package vaccine.appointment.system.vaccine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vaccine.appointment.system.common.enums.DelFlgEnum;
import vaccine.appointment.system.common.errorcode.CommonErrorCode;
import vaccine.appointment.system.common.exception.CommonException;
import vaccine.appointment.system.inventory.dataobject.Inventory;
import vaccine.appointment.system.inventory.mapper.InventoryMapper;
import vaccine.appointment.system.vaccine.dataobject.Vaccine;
import vaccine.appointment.system.vaccine.enums.VaccineTypeEnum;
import vaccine.appointment.system.vaccine.mapper.VaccineMapper;
import vaccine.appointment.system.vaccine.service.VaccineService;
import vaccine.appointment.system.vaccine.vo.AddVaccineRequest;
import vaccine.appointment.system.vaccine.vo.UpdateVaccineRequest;
import vaccine.appointment.system.vaccine.vo.VaccineListVO;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
public class VaccineServiceImpl implements VaccineService {
    @Autowired
    private VaccineMapper vaccineMapper;

    @Autowired
    private InventoryMapper inventoryMapper;

    @Override
    public Boolean insert(Vaccine vaccine) {
        vaccineMapper.insert(vaccine);
        return true;
    }

    @Override
    public Boolean delete(Integer id) {
        Vaccine vaccine = vaccineMapper.selectById(id);
        vaccineMapper.updateById(vaccine);
        return true;
    }

    @Override
    public Vaccine selectById(Integer id) {
        return vaccineMapper.selectById(id);
    }

    @Override
    public Boolean update(Vaccine vaccine) {
        vaccineMapper.updateById(vaccine);
        return true;
    }

    /**
     * 查询疫苗列表
     */
    @Override
    public Page<VaccineListVO> getVaccineList(Integer type, Integer pageNum, Integer pageSize) {
        // 1. 查询疫苗
        Page<Vaccine> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Vaccine> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());

        if (type != null) {
            queryWrapper.eq("type", type);
        }

        // 只查询未过期的疫苗
        queryWrapper.ge("validity_period", LocalDate.now());
        queryWrapper.orderByDesc("id");

        Page<Vaccine> vaccinePage = vaccineMapper.selectPage(page, queryWrapper);

        // 2. 组装VO
        Page<VaccineListVO> voPage = new Page<>(pageNum, pageSize);
        voPage.setTotal(vaccinePage.getTotal());

        List<VaccineListVO> voList = new ArrayList<>();
        for (Vaccine vaccine : vaccinePage.getRecords()) {
            VaccineListVO vo = new VaccineListVO();
            vo.setId(vaccine.getId());
            vo.setName(vaccine.getName());
            vo.setType(vaccine.getType());
            vo.setTypeDesc(VaccineTypeEnum.getDescByCode(vaccine.getType()));
            vo.setApplicableAgeGroup(vaccine.getApplicableAgeGroup());
            vo.setManufacturer(vaccine.getManufacturer());
            vo.setProductionDate(vaccine.getProductionDate());
            vo.setValidityPeriod(vaccine.getValidityPeriod());

            // 计算总库存
            QueryWrapper<Inventory> inventoryQueryWrapper = new QueryWrapper<>();
            inventoryQueryWrapper.eq("vaccine_id", vaccine.getId());
            inventoryQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
            List<Inventory> inventoryList = inventoryMapper.selectList(inventoryQueryWrapper);

            int totalStock = 0;
            for (Inventory inventory : inventoryList) {
                totalStock += inventory.getCount();
            }
            vo.setAvailableStock(totalStock);

            voList.add(vo);
        }
        voPage.setRecords(voList);

        return voPage;
    }

    /**
     * 添加疫苗（管理员功能）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addVaccine(AddVaccineRequest request) {
        // 验证过期日期必须大于生产日期
        if (!request.getExpirationDate().isAfter(request.getProductionDate())) {
            throw new CommonException(CommonErrorCode.INVALID_PARAMETER);
        }

        Vaccine vaccine = new Vaccine();
        vaccine.setName(request.getName());
        vaccine.setType(request.getType());
        vaccine.setManufacturer(request.getManufacturer());
        vaccine.setApplicableAgeGroup(request.getApplicableAgeGroup());
        vaccine.setProductionDate(request.getProductionDate());
        vaccine.setValidityPeriod(request.getExpirationDate());
        vaccine.setDelFlg(DelFlgEnum.NOT_DELETED.getCode());

        vaccineMapper.insert(vaccine);
        return true;
    }

    /**
     * 更新疫苗（管理员功能）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateVaccine(Integer vaccineId, UpdateVaccineRequest request) {
        Vaccine vaccine = vaccineMapper.selectById(vaccineId);
        if (vaccine == null || vaccine.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(CommonErrorCode.NOT_FOUND);
        }

        // 验证过期日期必须大于生产日期
        if (!request.getExpirationDate().isAfter(request.getProductionDate())) {
            throw new CommonException(CommonErrorCode.INVALID_PARAMETER);
        }

        vaccine.setName(request.getName());
        vaccine.setType(request.getType());
        vaccine.setManufacturer(request.getManufacturer());
        vaccine.setApplicableAgeGroup(request.getApplicableAgeGroup());
        vaccine.setProductionDate(request.getProductionDate());
        vaccine.setValidityPeriod(request.getExpirationDate());

        vaccineMapper.updateById(vaccine);
        return true;
    }

    /**
     * 删除疫苗（管理员功能）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteVaccine(Integer vaccineId) {
        Vaccine vaccine = vaccineMapper.selectById(vaccineId);
        if (vaccine == null || vaccine.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(CommonErrorCode.NOT_FOUND);
        }

        vaccine.setDelFlg(DelFlgEnum.DELETED.getCode());
        vaccineMapper.updateById(vaccine);
        return true;
    }

    /**
     * 查询所有疫苗列表（管理员功能，包含已过期的）
     */
    @Override
    public Page<VaccineListVO> getAllVaccineList(Integer type, Integer pageNum, Integer pageSize) {
        // 1. 查询疫苗
        Page<Vaccine> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Vaccine> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());

        if (type != null) {
            queryWrapper.eq("type", type);
        }

        // 不过滤过期疫苗
        queryWrapper.orderByDesc("id");

        Page<Vaccine> vaccinePage = vaccineMapper.selectPage(page, queryWrapper);

        // 2. 组装VO
        Page<VaccineListVO> voPage = new Page<>(pageNum, pageSize);
        voPage.setTotal(vaccinePage.getTotal());

        List<VaccineListVO> voList = new ArrayList<>();
        for (Vaccine vaccine : vaccinePage.getRecords()) {
            VaccineListVO vo = new VaccineListVO();
            vo.setId(vaccine.getId());
            vo.setName(vaccine.getName());
            vo.setType(vaccine.getType());
            vo.setTypeDesc(VaccineTypeEnum.getDescByCode(vaccine.getType()));
            vo.setApplicableAgeGroup(vaccine.getApplicableAgeGroup());
            vo.setManufacturer(vaccine.getManufacturer());
            vo.setProductionDate(vaccine.getProductionDate());
            vo.setValidityPeriod(vaccine.getValidityPeriod());

            // 计算总库存
            QueryWrapper<Inventory> inventoryQueryWrapper = new QueryWrapper<>();
            inventoryQueryWrapper.eq("vaccine_id", vaccine.getId());
            inventoryQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
            List<Inventory> inventoryList = inventoryMapper.selectList(inventoryQueryWrapper);

            int totalStock = 0;
            for (Inventory inventory : inventoryList) {
                totalStock += inventory.getCount();
            }
            vo.setAvailableStock(totalStock);

            voList.add(vo);
        }
        voPage.setRecords(voList);

        return voPage;
    }
}
